package Sys_Module;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Calendar;
import java.util.Scanner;
import java.util.concurrent.locks.LockSupport;

public class List_Main {
    public int num = 1;
    private Queue Waitlist = new Queue();// 新建等待队列
    // public Queue Worklist = new Queue();
    public Worker_Window worker_windows;// 新建工作窗口的类
    public Thread Wait_list_thread;
    public Thread Work_list_thread;
    public Thread Work_list_out_thread;
    public Thread Display_list_thread;
    public Thread LMControl_thread;
    private Server_Network SN48001;// 用于存储叫号机的指针
    private Server_Network SN48002;// 用于存储叫号机的指针
    private Server_Network SN48003;// 用于存储叫号机的指针
    public boolean CCaller = false, CWaiter = false, CWorker = false, ALL_Client_Status = false,
            Data_Restore_mode = false;;// 定义变量
    // 用于连接客户端的判断
    private Log_Module Log_Sys;// 创建日志
    private Scanner input = new Scanner(System.in);
    public int tempNum = 0;// 叫号的Num变量

    public List_Main(Log_Module Log_Sys) {// 定义构造函数

        this.Log_Sys = Log_Sys;// 传递指针
        wait_list();// 运行方法
        Wait_list_thread.start();// 启动等待队列的线程
        List_INIT();
        LMControl();
    }

    private void List_INIT() {
        String WaitLData = "", WorkerData = "";
        try {
            WaitLData = Cache_Read_IN("Wait_List");
            WorkerData = Cache_Read_IN("Work_List");
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (WaitLData != "" || WorkerData != "") {
            System.out.print("检测到上次异常退出，是否导入之前数据(1.导入/2.跳过):");
            int text = input.nextInt();
            if (text == 1) {
                Data_Restore_mode = true;
                if (WaitLData != "") {
                    if (Waitlist.list_restore_data(WaitLData) == true) {
                        num = Integer
                                .valueOf(
                                        (String) WaitLData.subSequence(WaitLData.lastIndexOf(",") + 1,
                                                WaitLData.length()))
                                + 1;
                        System.out.println("已导入");
                    } else {
                        System.out.println("导入失败");
                    }
                }
            }

        }
        // String WorkLData=Cache_Read_IN("Wait_List");
    }

    public void SETSN48003(Server_Network SN) {// 用于传递指针
        this.SN48003 = SN;
        worker_windows = new Worker_Window(SN, Log_Sys, Data_Restore_mode); // 新建类 传递指针与log指针
    }

    public void SETSN48002(Server_Network SN) {// 用于传递指针
        this.SN48002 = SN;
    }

    private boolean Check_ALL_Client() throws IOException {// 用于检测所有客户端方法
        if (CCaller == true && CWaiter == true && CWorker == true && ALL_Client_Status == false) {// 判断各个客户端的状态
            Log_Sys.Write_log("info", "各个客户端已连接完毕");
            ALL_Client_Status = true;// 设置为true 避免二次检测 二次输出日志
            Work_list_out_thread.start();
            LMControl_thread.start();
            return true;
        }
        return false;
    }

    private int Check_ALL_Client_CONNECT_NUM() {// 返回客户端的连接数 主要靠判断变量来递增
        int num = 0;
        if (CCaller == true) {
            num++;
        }
        if (CWaiter == true) {
            num++;
        }
        if (CWorker == true) {
            num++;
        }
        return num;
    }

    public void Change_Client_Connect_Status(int num)// 更改客户端的连接状态
    {
        switch (num) {// 传递客户端的端口
            case 48001:
                CCaller = true;// 更改布尔值
                try {
                    Log_Sys.Write_log("info", "叫号客户端已连接完毕");
                } catch (IOException e) {
                }
                break;
            case 48002:
                CWaiter = true;// 更改布尔值
                try {
                    Log_Sys.Write_log("info", "取号客户端已连接完毕");
                } catch (IOException e) {
                }
                break;
            case 48003:
                CWorker = true;// 更改布尔值
                try {
                    Log_Sys.Write_log("info", "工作窗口客户端已连接完毕");
                } catch (IOException e) {
                }
                break;
        }
    }

    public void wait_list() {

        Wait_list_thread = new Thread(new Runnable() {
            @Override
            public void run() {// 重写run方法
                try {
                    Log_Sys.Write_log("Thread info", "号码队列线程已启动");
                } catch (IOException e) {
                }

                while (true) {

                    LockSupport.park();// 挂起线程
                    try {
                        Log_Sys.Write_log("Wait Queue info",
                                "收到取号请求，新取号码:" + num + ",等待的号码数:" + Waitlist.list_get_length());
                    } catch (IOException e) {
                    }
                    Waitlist.list_put_in(num);// 放入等待队列
                    num += 1;

                    // 等加入网络编程后 这里需要加入wait函数

                }

            }

        });
    }

    public void Working(Server_Network SN) {
        this.SN48001 = SN;
        Work_list_out_thread = new Thread(new Runnable() {
            @Override
            public void run() {// 重写run方法
                try {
                    Log_Sys.Write_log("Thread info", "工作队列线程已启动");
                } catch (IOException e) {
                }

                while (true) {
                    // Worklist.list_get_out(); // 工作完成 移出队列
                    // System.out.println(Can_Working);
                    // if (Can_Working == true) {
                    for (int i = 1; i <= 5; i++) {

                        if (worker_windows.Window_status(i) == 0 && Waitlist.list.size() >= 1) {// 判断队列大小是否大于1 和
                                                                                                // 获取窗口的态
                            tempNum = Waitlist.list_get_out();// 返回队列的值
                            worker_windows.Put_IN_Windows(tempNum, i);// 放入worker窗口内,传递Num和i窗口号
                            SN48001.output("info:" + "请" + tempNum + "号到窗口" + i + "办理业务");
                        }
                    }

                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    // }

                }
            }
        });

    }

    public void LMDisplay() {
        Display_list_thread = new Thread(new Runnable() {
            @Override
            public void run() {// 重写run方法
                try {
                    Log_Sys.Write_log("Thread info", "服务器显示线程已启动");
                } catch (IOException e) {
                }
                while (true) {
                    try {
                        Check_ALL_Client();// 检测各个客户端状态
                        clear_control_board();
                        if (ALL_Client_Status == true) {// 如果所有客户端状态为真
                            System.out.println("当前等待：" + Waitlist.list_display());// 显示等待队列当前数据
                            System.out.println("当前工作：" + worker_windows.Display_All_Windows());// 显示工作队列当前数据
                            // System.out.println("TTTT：" + Waitlist.list_display()); //测试list_display的数据
                            Cache_Write_IN("Wait_List", Waitlist.list_display());
                            Cache_Write_IN("Work_List", worker_windows.OutputData_All_Windows());
                            System.out.print("服务器控制台(1.退出系统)：");
                        } else {
                            System.out.println("等待客户端连接(" + Check_ALL_Client_CONNECT_NUM() + "/3)");
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    try {
                        Thread.sleep(1000);// 每秒刷新
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        Display_list_thread.start();// 运行线程
    }

    public void LMControl() {
        LMControl_thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    Integer ls = input.nextInt();
                    if (ls == 1) {
                        Display_list_thread.stop();
                        try {
                            Cache_Delete("Work_List");
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        try {
                            Cache_Delete("Wait_List");
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        SN48001.output("ShutdownNow");
                        SN48002.output("ShutdownNow");
                        SN48003.output("ShutdownNow");
                        System.exit(0);
                    }
                }
            }
        });
    }

    // 以下添加断电重启功能

    private static String Cache_getlujin() {// 获取路径程序
        File directory = new File("");// 设定为当前文件夹
        String text = "";
        try {
            // System.out.println(directory.getCanonicalPath());// 获取标准的路径
            text = directory.getAbsolutePath();// 获取绝对路径
        } catch (Exception e) {
        }
        return text + "\\cache\\";
    }

    private String Cahce_Get_File_Name(String name) throws IOException {
        Calendar ca_data = Calendar.getInstance(); // 初始化对象
        String temp; // 临时变量

        temp = name + " " + String.valueOf(ca_data.get(Calendar.YEAR)) + "-"
                + String.valueOf(ca_data.get(Calendar.MONTH) + 1) + "-" + String.valueOf(ca_data.get(Calendar.DATE))
                + ".cache";// 输出当前期
        File temp_file = new File(temp);
        if (temp_file.exists() == false) { // 检测文件是否存在
            temp_file.createNewFile(); // 如果文件不存在则创建
        }
        return temp;
    }

    public synchronized void Cache_Write_IN(String name, String data) throws IOException {

        String filename = Cahce_Get_File_Name(Cache_getlujin() + name);
        FileWriter cache_file_writer = null; // 新建writer file对象
        BufferedWriter cache_Buff_writer = null; // 新建buff writer 对象

        try {
            cache_file_writer = new FileWriter(filename, false); // 第二个参数为true 允许对日志文件的续写
        } catch (IOException e) {
            e.printStackTrace();
        }
        cache_Buff_writer = new BufferedWriter(cache_file_writer);
        cache_Buff_writer.flush();
        cache_Buff_writer.write(data);
        cache_Buff_writer.close();
        cache_file_writer.close();
    }

    private void Cache_Delete(String name) throws IOException {
        File file = new File(Cahce_Get_File_Name(Cache_getlujin() + name));
        file.delete();
    }

    public synchronized String Cache_Read_IN(String name) throws IOException {
        String temp = "", temp2 = "";
        String filename = Cahce_Get_File_Name(Cache_getlujin() + name);
        FileReader cache_file_reader = null; // 新建reader file对象
        BufferedReader cache_Buff_reader = null; // 新建buff reader 对象
        try {
            cache_file_reader = new FileReader(filename);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        cache_Buff_reader = new BufferedReader(cache_file_reader);

        while ((temp = cache_Buff_reader.readLine()) != null) {
            temp2 = temp2 + temp;
        }
        cache_Buff_reader.close();
        cache_file_reader.close();
        return temp2;

    }

    private void clear_control_board() throws IOException {
        System.out.print("\033[H\033[2J");
        System.out.flush();
    }

    @Override
    protected void finalize() throws Throwable { // 析构函数 定义
        super.finalize();
        input.close();
    }

}